package com.ruoyi.aitcommon.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;

import com.alibaba.fastjson.JSONObject;
import com.ruoyi.aitcommon.function.BiConsumerEx;
import com.ruoyi.aitcommon.function.BiFunctionEx;
import com.ruoyi.common.utils.StringUtils;

public class MapUtils {
	public static Map<String,Object> combineMap(Map<String,Object> map1,Map<String,Object> map2){
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		retmap.putAll(map1);
		retmap.putAll(map2);
		return retmap;
	}

	/**
	 * 构造新map,key和value相同
	 * @param list
	 * @return
	 */
	public static Map<String,Object> newMap(List<String> list){
		return newMap(list.toArray(new String[list.size()]));
	}
	/**
	 * 构造新map,key和value相同
	 * @param list
	 * @return
	 */
	public static Map<String,Object> newMap1(List<Object> list){
		List<String> stringList = new ArrayList<>();
		for (Object obj : list) {
				if(ObjUtils.isNotBlank(obj))
					stringList.add(obj.toString());
		}
		return newMap(stringList);
	}

	public static Map<String,Object> newMap(List<Map<String,Object>> list,String key){
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		for(Map<String,Object> map:list){
			retmap.put(map.get(key).toString(),map);
		}
		return retmap;
	}

	/**
	 * 构造新map,key和value相同
	 * @param list
	 * @return
	 */
	public static Map<String,Object> newMap(String[] list){
		Map<String, Object> retmap=new LinkedHashMap<>();
		for(Object item:list) {
			retmap.put(item.toString().trim(), item);
		}
		return retmap;
	}
	
	/**
	 * 遍历所有key,调用lamda函数,这里不构造新map
	 * 这里不进行递归操作,递归操作使用pathForeach
	 * @param map
	 * @param action
	 * @return 
	 */
	public static void foreach(Map<String,Object> map,BiConsumer<String,Object> action){
		map.forEach(action);
	}
	
	/**
	 * 遍历所有key,调用lamda函数,构造新的map
	 * 这里不进行递归操作,递归操作使用pathMap
	 * @param map
	 * @param action
	 * @return 构造后的新map
	 */
	public static Map<String,Object> map(Map<String,Object> map,BiFunction<String,Object,Object[]> action){
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		
		for(String key:map.keySet()) {
			Object[] rets = action.apply(key,map.get(key));
			retmap.put(rets[0].toString(), rets[1]);
		}
		
		return retmap;
	}
	
	/**
	 * 遍历所有key,trim(key),value不变
	 * @param map
	 * @return 新map
	 */
	public static Map<String,Object> trim(Map<String,Object> map){
		return MapUtils.map(map, (key,value)->{return new Object[] {key.trim(),value};});
	}
	
	/**
	 * 依据分隔符,获取分隔符后面的字段
	 * @param map 原map
	 * @param fengge 分隔符,如果存在多个,从第一个分隔符后的字段复制
	 * @return 分隔符后的map
	 */
	public static Map<String,Object> subMap(Map<String,Object> map,String fengge){
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		boolean ismatch=false;
		for(String key:map.keySet()) {
			if(ismatch) {
				//分隔符之后的字段
				retmap.put(key, map.get(key));
			}
			if(key.equals("fengge")) {
				ismatch=true;
			}
		}
		return retmap;
	}

	/**
	 * 递归循环map中的所有key(包含子map),调用lamda函数处理,不构造新map
	 * 只在叶子节点执行action
	 * @param map 树形MAP
	 * @param action lamda函数,参数 key,val,无返回
	 * @return 处理后的原map
	 */
	@SuppressWarnings("unchecked")
	public static void pathForeach(Map<String,Object> map,BiConsumerEx<String,Object> action) throws Exception {
		for(String key:map.keySet()) {
			Object val=map.get(key);
			if(val instanceof Map) {
//				值为子map对象,递归调用
				pathForeach((Map<String,Object>)val,action);
			} else {
//				值为其他对象,直接处理
				action.accept(key,val);
			}
		}
	}
	
	/**
	 * 递归循环map中的所有key(包含子map),调用lamda函数处理,并返回构造的新map
	 * 类似于JS对象的map方法
	 * @param map
	 * @param action lamda函数,参数 key,val,返回 Object[]
	 * @return 处理后的新增map
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Map<String,Object> pathMap(Map<String,Object> map,BiFunctionEx<String,Object,Object[]> action) throws Exception{
//		构造的新map
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		for(String key:map.keySet()) {
			Object val=map.get(key);
			if(val instanceof Map) {
//				值为子map对象,递归调用
				Map<String, Object> map2 = pathMap((Map<String,Object>)val,action);
				retmap.put(key,map2);
			}else {
//				值为其他对象,直接处理
				Object[] rets = action.apply(key, val);
				retmap.put(rets[0].toString(), rets[1]);
			}
		}
		return retmap;
	}

	/**
	 * 对pathMap增强
	 * 1 增加value=list时的处理
	 * 2 增加value=map时,自身的重复调用
	 * @param map
	 * @param action
	 * @return
	 * @throws Exception
	 */
	public static Map<String,Object> pathMap1(Map<String,Object> map,BiFunctionEx<String,Object,Object[]> action) throws Exception{
//		构造的新map
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		for(String key:map.keySet()) {
			Object val=map.get(key);
			if(val instanceof Map) {
//				值为子map对象,递归调用
				Map<String, Object> map2 = pathMap1((Map<String,Object>)val,action);
//				增加自身调用
				Object[] rets = action.apply(key, map2);
				retmap.put(rets[0].toString(), rets[1]);
			} else if (val instanceof List) {
//				值为list,循环调用
				List<Map<String,Object>> retlist=new ArrayList<>();
				for(Object item:(List<Object>)val){
					if(item instanceof Map){
						Map<String, Object> map2 = pathMap1((Map<String,Object>)item,action);
						retlist.add(map2);
					}
				}
//				增加自身调用
				Object[] rets = action.apply(key, retlist);
				retmap.put(rets[0].toString(), rets[1]);
			} else {
//				值为其他对象,直接处理
				Object[] rets = action.apply(key, val);
				retmap.put(rets[0].toString(), rets[1]);
			}
		}
		return retmap;
	}
	
	/**
	 * 依据路径获取map中的list
	 * 被getPathObject调用
	 * @param path
	 * @param list
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	private static List<Object> getPathList(String path, List<Object> list) throws Exception {
		List<Object> retlist = new ArrayList<Object>();
//		循环list
		for (Object item : list) {
//				List里面是Map
			if (item instanceof Map) {
				Object val1 = getPathObject(path, (Map<String, Object>) item);
				retlist.add(val1);
			} else if(item instanceof List){
//					list里面是个list
				List<Object> list1 = getPathList(path, (List<Object>) item);
				retlist.add(list1);
			} else {
				String msg="MapList解析类型出错.下级PATH:%s,值:%s.该值必须是MAP或LIST类型";
				msg=String.format(msg, path,item.toString());
				throw new Exception(msg);
			}
		}
		return retlist;
	}
	
	
	/**
	 * 依据路径获取JSON字符串中的object
	 * @param path 路径
	 * @param jsonstr 
	 * @return 路径指向的值Object
	 * @throws Exception
	 */
	public static Object getPathObject(String path,String jsonstr) throws Exception {
		if(StringUtils.isBlank(path)) return null;
		if(StringUtils.isBlank(jsonstr)) return null;
		JSONObject json = JSONUtils.parseObject(jsonstr);
		if(json==null) return null;
		return getPathObject(path,json);
	}
	
	/**
	 * 判断路劲在map中是否存在
	 * @param path 路径
	 * @param map map对象,支持多级map
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static boolean containsPathObject(String path,Map<String,Object> map) {
//		获取当前节点值
		String[] paths = StringUtils.split(path, '.');
		if(!map.containsKey(paths[0]))
			return false;
		
//		获取下级节点
		List<String> subList = Arrays.asList(paths).subList(1, paths.length);
		String subPath = StringUtils.join(subList, '.');
		if (StringUtils.isBlank(subPath)) {
//			末级节点
			return true;
		} else {
			Object val = map.get(paths[0]);
			if (val == null)
				return false;
			
//			非末级节点，递归获取下级节点
//			当前节点为MAP
			if (val instanceof Map)
				return containsPathObject(subPath, (Map<String, Object>) val);
//			当前节点为List
			else if (val instanceof List) {
				return containsPathList(subPath,(List<Object>)val);
			} else
				return false;
		}
	}

	/**
	 * 依据路径判断map中是否存在list
	 * @param path
	 * @param list
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static boolean containsPathList(String path, List<Object> list) {
		List<Boolean> blist = new ArrayList<Boolean>();
		boolean bool=false;
//		循环list
		for (Object item : list) {
//				List里面是Map
			if (item instanceof Map) {
				bool = containsPathObject(path, (Map<String, Object>) item);
				blist.add(bool);
			} else {
//					list里面是个list
				bool = containsPathList(path, (List<Object>) item);
				blist.add(bool);
			}
		}
		for(Boolean b:blist) {
			if(b==false)
				return false;
		}
		return true;
	}
	
	/**
	 * 依据path获取map中的对象,支持多级,通过"."分级
	 * @param path 路径,支持"."分级
	 * @param map 存储对象的map
	 * @return path对应的object,如果没有,返回null
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static Object getPathObject(String path, Map<String, Object> map) throws Exception {
		try {
	//		获取当前节点值
			String[] paths = StringUtils.split(path, '.');
			Object val = map.get(paths[0]);
			if (val == null)
				return null;
	//		获取下级节点
			List<String> subList = Arrays.asList(paths).subList(1, paths.length);
			String subPath = StringUtils.join(subList, '.');
			if (StringUtils.isBlank(subPath)) {
	//			末级节点
				return val;
			} else {
	//			非末级节点，递归获取下级节点
	//			当前节点为MAP
				if (val instanceof Map)
					return getPathObject(subPath, (Map<String, Object>) val);
	//			当前节点为List
				else if (val instanceof List) {
					return getPathList(subPath,(List<Object>)val);
				} else
					return null;
			}
		}catch(Exception ex) {
			String msg="MAP解析错误,PATH:%s";
			msg=String.format(msg, path);
			throw new Exception(msg,ex);
		}
	}
	
	/**
	 * 依据路径获取map对象中指定值
	 * @param path
	 * @param map
	 * @return 返回指定值的toString()
	 * @throws Exception
	 */
	public static String getPathString(String path,Map<String, Object> map) throws Exception {
		Object ret=getPathObject(path,map);
		if(ret!=null) return ret.toString();
		else return null;
	}
	
	/**
	 * 依据路径设置object，注意：路径上不能存在list节点
	 * 中间节点自动创建为LinkedHashMap
	 * @param path 设置路径,用.作为分隔符
	 * @param map 被设置的map
	 * @param value 被设置的值
	 * @return 设置后的新map
	 */
	@SuppressWarnings("unchecked")
	public static Map<String, Object> putPathObject(String path,Map<String, Object> map,Object value) throws Exception {
		Map<String, Object> tmpmap=map;
//		获取当前节点值
		String[] paths = StringUtils.split(path, '.');
		for(int i=0;i<=paths.length-1;i++) {
			if(i==paths.length-1) {
//				末级节点
				if(tmpmap!=null)
					tmpmap.put(paths[i], value);
			}else {
//				中间节点
				if(tmpmap.get(paths[i])==null) {
//					中间节点,创建MAP
					Map<String, Object> tmpmap1=new LinkedHashMap<>();
					tmpmap.put(paths[i], tmpmap1);
					tmpmap=tmpmap1;
				}else {
//					中间节点,使用MAP
					if(tmpmap.get(paths[i]) instanceof Map)
						tmpmap=(Map<String, Object>)tmpmap.get(paths[i]);
					else
						throw new Exception("路径"+path+"：不能存在list节点！");
				}
			}
		}
		return map;
	}
	
	/**
	 * 将fromMap中的key，依据映射表，转换为 新key->value 的字段,值不变
	 * 举例:A:1000,转换为B:1000,映射表 A->B
	 * @param fromMap 被转换的map
	 * @param transMap 映射表
	 * @return 转换后的map
	 */
	public static Map<String,Object> transObjectKeytoValue(Map<String,Object> fromMap,Map<String,Object> transMap) {
		Map<String,Object> retmap=new LinkedHashMap<String,Object>();
		
//		映射前先trim
		Map<String, Object> map1 = MapUtils.trim(transMap);
		Map<String, Object> values1 = MapUtils.trim(fromMap);
		
		for(Map.Entry<String, Object> item : values1.entrySet()) {
//			如果对象map包含values.key
			if(map1.containsKey(item.getKey())) {
//				字段映射:map.value<--map.key,值=values里面的值
				retmap.put(map1.get(item.getKey()).toString(), item.getValue());
			}
		}
		return retmap;
	}
	
	/**
	 * 将fromMap中的key，依据映射表，转换为新key->value字段,值不变
	 * 举例:A:1000,转换为B:1000,映射表 B->A
	 * @param fromMap 被转换的map
	 * @param transMap 映射表
	 * @return 新map
	 */
	public static Map<String,Object> transObjectValuetoKey(Map<String,Object> fromMap,Map<String,Object> transMap) {
		Map<String,Object> map1=new LinkedHashMap<String,Object>();
//		将map中的key:value映射互换位置
		for(Map.Entry<String, Object> item : transMap.entrySet()) {
			map1.put(item.getValue().toString(), item.getKey());
		}
//		调用key->value
		return transObjectKeytoValue(fromMap,map1);
	}
	
	/**
	 * 从map中获取value,如果没有,返回默认值
	 * 用于字典翻译
	 * @param key key值
	 * @param map map字典
	 * @param defvalue 默认值
	 * @return map的value值或默认值
	 */
	public static String transFieldValue(Object key,Map<String,Object> map,String defvalue) {
		if(key==null) return defvalue;
		if(map.containsKey(key)) {
			return map.get(key).toString();
		}else {
			return defvalue;
		}
	}
}
